package com.glp.work.flow.workflow.command;

import com.glp.work.flow.constant.APICode;
import com.glp.work.flow.exception.APIException;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.EndEvent;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.editor.language.json.converter.util.CollectionUtils;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 审批不通过
 *
 * @author pengjia
 * @version 2020年6月5日 上午8:50:49
 */
@Component
@Slf4j
public class CommonEndProcessInstanceCmd implements Command<Void> {

    private String procInstanceId;
    private static RuntimeService runtimeService;
    private static RepositoryService repositoryService;

    public CommonEndProcessInstanceCmd() {
    }

    public CommonEndProcessInstanceCmd(String procInstanceId) {
        this.procInstanceId = procInstanceId;
    }

    @Override
    public Void execute(CommandContext commandContext) {
        log.info("审批不通过，结束当前流程。processId={}", procInstanceId);
        String processDefId = runtimeService.createProcessInstanceQuery().processInstanceId(procInstanceId).singleResult().getProcessDefinitionId();
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefId).singleResult();
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
        Optional<FlowElement> optional =  bpmnModel.getMainProcess().getFlowElements().stream().filter(fe -> fe instanceof EndEvent).findFirst();
        if(optional.isPresent()) {
            List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(this.procInstanceId).list();
            if(CollectionUtils.isNotEmpty(executions)) {
                executions = executions.stream().filter(predicate->{
                    if(predicate instanceof ExecutionEntityImpl) {
                        if (((ExecutionEntityImpl) predicate).isProcessInstanceType()) {
                            return false;
                        } else {
                            if (((ExecutionEntityImpl) predicate).isScope()) {
                                return false;
                            } else if (((ExecutionEntityImpl) predicate).isMultiInstanceRoot()) {
                                return false;
                            } else {
                                return true;
                            }
                        }
                    }
                    return false;
                }).collect(Collectors.toList());
                List<String> executionIds = executions.stream().map(Execution::getId).collect(Collectors.toList());
                log.info("审批不通过，根据processId，查询所有执行中的executioIds，结束当前流程。processId={}, executionIds={}", procInstanceId, executionIds);
                runtimeService.createChangeActivityStateBuilder().processInstanceId(this.procInstanceId).moveExecutionsToSingleActivityId(executionIds, optional.get().getId()).changeState();
            }else {
                throw new APIException(APICode.DATA_ERROR, "执行【审批不通过】失败，当前流程实例已结束或没有正在执行的用户任务！");
            }
        }
        return null;
    }


    @Autowired
    public void setRuntimeService(RuntimeService runtimeService) {
        CommonEndProcessInstanceCmd.runtimeService = runtimeService;
    }

    @Autowired
    public void setRepositoryService(RepositoryService repositoryService) {
        CommonEndProcessInstanceCmd.repositoryService = repositoryService;
    }


}
